--[[ 长空超翼神脚本,作用是显示坐标和在坐标位置显示一个红色方块
  可作为cave stg游戏的模版
  
  保留了u16和u8两种计算方法,没办法啊...
  
  测试后决定使用十字线显示,炸弹用read_u16的方法读取
  
  By setycyas @2025-01-27
]]

-- 打包成GAME模块,最后导出
local GAME = {
  -- 分辨率
  X_RESOLUTION = 224,
  Y_RESOLUTION = 448,
  -- 横坐标纵坐标内存地址
  X_ADDR_HIGH = 0x88EE9A,
  X_ADDR_LOW = 0x88EE9B,
  Y_ADDR_HIGH = 0x88EE98,
  Y_ADDR_LOW = 0x88EE99,
  -- 如果仅用read_u16读取坐标和计算,就设定为true
  USE_U16 = false,
  -- 残机和炸弹地址
  LIFE_ADDR = 0x8139D7,
  BOMB_ADDR = 0x80EEBA,
  STONE_ADDR = 0x80ef04, -- 大端16bit,用read_u16读取
  -- 坐标最终修正比例
  X_OFFSET = 0.0,
  Y_OFFSET = 0.0,
  -- 自机中心方块的半长半高,单位为MAME的屏幕比例
  BOX_HALF_WIDTH = 0.005,
  BOX_HALF_HEIGHT = 0.005,
  --HEIGHT_OFFSET = 0.02,
  -- 两个十字方块的半长半高
  XBOX_HALF_WIDTH = 0.032,
  XBOX_HALF_HEIGHT = 0.0065,
  YBOX_HALF_WIDTH = 0.0065,
  YBOX_HALF_HEIGHT = 0.035,
  -- 中心方块的边框颜色和中心颜色
  BOX_BORDER_COLOR = 0x88ff0000,
  BOX_COLOR = 0x88ff0000,
  -- 十字方块的边框颜色和中心颜色
  CROSS_BORDER_COLOR = 0x99ff00ff,
  CROSS_FULL_COLOR = 0x000000ff, -- 有觉圣石时的颜色,颜色与透明度分开
  CROSS_FULL_ALPHA = 0x66, -- 满觉圣石时的透明度
  CROSS_EMPTY_COLOR = 0xAAaaaaaa, -- 无觉圣石时的颜色
  -- 十字线,易被自机子弹遮盖,建议设为子弹的反色
  CROSS_LINE_WIDTH = 0.002, --十字线宽度
  CROSS_LINE_COLOR = 0x77ff00ff, --颜色
  -- mame api用的对象
  mem = manager.machine.devices[':maincpu'].spaces['program'],
  container = manager.machine.screens[":screen"].container,
  ui_container = manager.machine.render.ui_container,
}

-- 刷新设备,成功获取设备返回true,否返回false
function GAME.refreshDevices()
  GAME.mem = manager.machine.devices[':maincpu'].spaces['program']
  GAME.container = manager.machine.screens[":screen"].container
  GAME.ui_container = manager.machine.render.ui_container
  
  if (GAME.mem and GAME.container and GAME.ui_container) then
    return true
  else
    return false
  end
end

-- 坐标变换,从内存坐标变为屏幕显示位置,返回0.0-1.0的浮点数,
function GAME.getX_u16()
  local x
  --实际像素位置就是x的4倍可能四舍五入!最后计算屏幕比例才除以分辨率!
  x = 4.0*GAME.mem:read_u16(GAME.X_ADDR_HIGH)/0x100 
  result = x/(GAME.X_RESOLUTION) 
  
  return result+GAME.X_OFFSET
end
function GAME.getY_u16()
  local y
  --实际像素位置就是y的4倍可能四舍五入!最后计算屏幕比例才除以分辨率!
  y = 4.0*GAME.mem:read_u16(GAME.Y_ADDR_HIGH)/0x100
 
  result = y/(GAME.Y_RESOLUTION) 
  
  return result+GAME.Y_OFFSET
end
function GAME.getX_u8()
  local xhigh, xlow, result
  xhigh = GAME.mem:read_u8(GAME.X_ADDR_HIGH)
  xlow = GAME.mem:read_u8(GAME.X_ADDR_LOW)
  result = xhigh/56.0 -- 56=224/4
  if (xlow > 200) then
    xlow = 200
  end
  result = result+(xlow-56)/14336.0 -- 14336=(256/4)*224

  return result
end
function GAME.getY_u8()
  local ylow, yhigh, result
  ylow = GAME.mem:read_u8(GAME.Y_ADDR_LOW)
  yhigh = GAME.mem:read_u8(GAME.Y_ADDR_HIGH)
  result = yhigh/112.0 -- 112=448/4
  result = result+ylow/28672.0 -- 28672=(256/4)*448
  
  return result
end

-- 数据显示
function GAME.showInfo(GAMEList ,position, color)
  for index, value in ipairs(GAMEList) do
    GAME.ui_container:draw_text(position, 0.05*index, value, color)
  end
  
end

-- 监视数据显示
function GAME.check()
  local bomb --内存数据
  bomb = GAME.mem:read_u16(GAME.BOMB_ADDR)
  -- 显示炸弹
  GAME.ui_container:draw_text(0.75, 0.07, 
    string.format("bomb=%d", bomb),
    0xFF002b36, 0xFF839496
  )
end

-- 显示自机的几个方框,xfloat,yfloat是浮点数坐标
-- 显示中心
function GAME.showCenter(xfloat, yfloat)

  GAME.container:draw_box(
    yfloat-GAME.BOX_HALF_HEIGHT,
    xfloat-GAME.BOX_HALF_WIDTH,
    yfloat+GAME.BOX_HALF_HEIGHT,
    xfloat+GAME.BOX_HALF_WIDTH,
    GAME.BOX_BORDER_COLOR, GAME.BOX_COLOR
  )
  
end
-- 显示十字方框
function GAME.showCrossBox(xfloat, yfloat)
  local stone --觉圣石,最大500
  local crossColor -- 十字颜色
  local alpha -- 透明度
  
  -- 通过觉圣石计算十字的颜色
  stone = GAME.mem:read_u16(GAME.STONE_ADDR)
  if (stone > 500) then
    stone = 500
  end
  
  if (stone == 0) then
    crossColor = GAME.CROSS_EMPTY_COLOR
  else
    alpha = GAME.CROSS_FULL_ALPHA*(stone/500)+0x11*(500-stone)/500
    alpha = math.floor(alpha+0.5)*0x1000000
    crossColor = alpha+GAME.CROSS_FULL_COLOR
  end
  
  -- 十字形方框
  -- 横向框
  GAME.container:draw_box(
    yfloat-GAME.XBOX_HALF_HEIGHT,
    xfloat-GAME.XBOX_HALF_WIDTH,
    yfloat+GAME.XBOX_HALF_HEIGHT,
    xfloat+GAME.XBOX_HALF_WIDTH,
    GAME.CROSS_BORDER_COLOR, crossColor
  )
  -- 竖向框
  GAME.container:draw_box(
    yfloat-GAME.YBOX_HALF_HEIGHT,
    xfloat-GAME.YBOX_HALF_WIDTH,
    yfloat+GAME.YBOX_HALF_HEIGHT,
    xfloat+GAME.YBOX_HALF_WIDTH,
    GAME.CROSS_BORDER_COLOR, crossColor
  )
  
end
-- 显示十字线
--[[
function GAME.showCrossLine(xfloat, yfloat)
  -- 横线
  GAME.container:draw_line(
    0.0, xfloat, 1.0, xfloat, GAME.CROSS_LINE_COLOR
  )
  -- 竖线
  GAME.container:draw_line(
    yfloat, 0.0, yfloat, 1.0,GAME.CROSS_LINE_COLOR
  )
  
end
]]
function GAME.showCrossLine(xfloat, yfloat)
  -- 横线
  GAME.container:draw_box(
    0.0, xfloat-GAME.CROSS_LINE_WIDTH, 
    1.0, xfloat+GAME.CROSS_LINE_WIDTH, 
    GAME.CROSS_LINE_COLOR, GAME.CROSS_LINE_COLOR
  )
  -- 竖线
  GAME.container:draw_box(
    yfloat-GAME.CROSS_LINE_WIDTH, 0.0,
    yfloat+GAME.CROSS_LINE_WIDTH, 1.0,
    GAME.CROSS_LINE_COLOR, GAME.CROSS_LINE_COLOR
  )
  
end


--[[ **************************
  主函数,绑定后每一帧执行一次该函数
]]
function GAME.main()
  local xfloat, yfloat -- 最终浮点数坐标
  
  -- 刷新设备,并判断当前帧能否操作
  if (not GAME.refreshDevices()) then
    return
  end

  -- 获取自己屏幕坐标
  if GAME.USE_U16 then
    xfloat = GAME.getX_u16()
    yfloat = GAME.getY_u16()
  else
    xfloat = GAME.getX_u8()
    yfloat = GAME.getY_u8()
  end
  
  -- 数据监视
  GAME.check()
  -- 显示角色中心辅助线
  if (xfloat > 0.0) and (yfloat > 0.0) then
    -- 十字线
    GAME.showCrossLine(xfloat, yfloat)
    -- 十字方框
    --GAME.showCrossBox(xfloat, yfloat)
    -- 中心
    GAME.showCenter(xfloat, yfloat)
  end
  
end

-- 绑定每一帧执行的函数
emu.register_frame_done(GAME.main, "frame")

return GAME
